//-----------------------------------------------------
// nebulaState.h
//-----------------------------------------------------

/**
 * @file nebulaState.h
 *
 * Contains the class that represents a state of the Nebula application.
 * All the states of the application that want to use Nebula for drawing
 * must extend this class and implement it's virtual methods.
 *
 * @see application::CApplicationState
 * @see application::CApplication
 *
 */

#pragma once

#include "applicationState.h"
#include <mathlib\matrix.h>

class nMayaCamControl;	// FIXME: Implement our own camera control system

namespace application {

		class CNebulaApplication;

		/**
			Class CNebulaState: represents an application state with nebula drawing capabilities
			(menu, game, end,...). OnRun() is divided in the necessary phases to draw with Nebula.
			OnRun() is now a Template Method, that calls runLogic(), processUserInput() and paint3D().

			The camera management is delegated to the specific states that must change it's position
			and orientation according to it's behavior during runLogic(). This position/orientation is
			given by the attribute cameraMatrix.

			For testing purposes this class implements a default camera driven by mouse (nMayaCamControl),
			that is updated calling updateDefaultCamera(). It's position can also be restored with
			resetDefaultCamera(). The sates that use this camera must call it's reset during activation,
			and it's update during the update logic phase.
		*/

		class CNebulaState : public CApplicationState {

		public:
			nMayaCamControl *_camControl;	// Default camera controller. Driven by mouse

		protected:
			matrix44 cameraMatrix;		// Camera Matrix. Initially the identity matrix
			CNebulaApplication *_nebulaApp;	// The application the state belongs to

		public:

			// Class constructor
			CNebulaState(CNebulaApplication *nebulaApp);

			// Class destructor
			virtual ~CNebulaState();

			// Returns the 4x4 translation/rotation matrix the derived classes will update this
			// attribute to move the camera during it's runLogic() phase
			matrix44 &getCameraMatrix() { return cameraMatrix; }

			// Set a new camera matrix. @param the new 4x4 camera matrix
			void setCameraMatrix(const matrix44 &m) { cameraMatrix = m; }

			// Function called during state creation to initialize it's elements
			virtual void onCreate();

			// Function called during state destruction
			virtual void onDestroy();

			// Function called when the state is activated
			virtual void onActivate();

			// Function called on state deactivation
			virtual void onDeactivate();

			// Function encapsulating the state functionality
			virtual void onRun();

			/***************************************************/
			/*		MOUSE DRIVEN CAMERA CONTROL FUNCTIONS      */
			/***************************************************/

			// Reset the default camera to it's initial position,...
			void resetDefaultCamera();

			// Change the default camera position according to the mouse events
			// FIXME: This method will be called from runLogic() of the particular state
			// this breaks the decoupling between logic and event processing because the
			// position update ask for events to the intputServer
			void updateDefaultCamera();

		protected:

			// Method overridden by the derived classes that runs the logic associated to the state.
			virtual void runLogic();

			// Method overridden by the derived classes that paints the 3d part of the scene.
			virtual void paint3D() {}

			// Method called from onRun() when it's necessary to process events. The different
			// derived classed will implement it to react to events depending on it's state
			virtual void processUserInput();

			// Method called from onRun() to process the commands inserted in the HUD queue.
			virtual void processHUDCommandQueue();

			// Method called from processHUDCommandQueue() to process a particular HUD event.
			// This method will be specialized by the derived classes to modify the default
			// behavior (change the application state)
			virtual void processHUDCommand(std::string command);

		}; // class CNebulaState


} // namespace application